package com.ggboy.sc.pl.project.es.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import com.ggboy.sc.pl.project.es.dao.TestMapper;
import com.ggboy.sc.pl.project.es.model.DocBean;
import com.ggboy.sc.pl.project.es.model.SampleEntity;
import com.ggboy.sc.pl.project.es.model.TestPoetry;
import com.ggboy.sc.pl.project.es.service.TestService;
import com.ggboy.sc.pl.project.es.util.EsUtils;
import com.ggboy.sc.pl.project.es.util.GsonUtil;

@SuppressWarnings({ "unused", "unchecked", "serial"})
@Service
public class TestServiceImpl implements TestService{

	@Autowired
	private TestMapper testMapper;

    @Resource(name="localEsClient")
    private ElasticsearchTemplate elasticsearchTemplate;
    
	@Override
	public List<Map<String, Object>> list() {
		return testMapper.lists();
	}

	@Override
	public Map<String, Object> bigData(Integer size) {
		SampleEntity entity = null;
		List<IndexQuery> list=new ArrayList<IndexQuery>();
		IndexQuery indexQuery = null;
		for(int i=0;i<size;i++) {
			entity = new SampleEntity();
			entity.setId(System.currentTimeMillis()+Math.round(Math.random()*100000000)+"");
			entity.setContent(System.currentTimeMillis()+Math.round(Math.random()*5)+"");
			entity.setSex((int)Math.round(Math.random()*5));
			entity.setTitle("SampleEntity");
			entity.setUpdatetime(new Date());
			indexQuery = new IndexQueryBuilder().withId(entity.getId()).withObject(entity).build();
			list.add(indexQuery);
		}
		elasticsearchTemplate.bulkIndex(list);
		Map<String, Object > h = new HashMap<String, Object>(){{
		      put("msg","插入数据"+size+"条");    
		}};
		return h;
	}

	@Override
	public Map<String, Object> dataPage(Integer page,Integer pageSize) {
		page=page==null?0:page;
		pageSize=pageSize==null?10:pageSize;
		page=page*pageSize;
		SearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withPageable(PageRequest.of(page, pageSize))
				.build(); // 模糊分页
		List<SampleEntity> list = elasticsearchTemplate.queryForList(searchQuery, SampleEntity.class);
		Map<String, Object> h = new HashMap<String, Object>() {
			{
				put("msg", "成功");
			}
		};
		h.put("data", list);
		return h;
	}

	@Override
	public Map<String, Object> poetry() {
		TestPoetry poetry = null; 
		IndexQuery index =null;
		List<IndexQuery> list =new ArrayList<IndexQuery>();
		for(int i=0;i<EsUtils.getTitle().size();i++) {
			poetry = new TestPoetry();
			index = new IndexQuery();
			poetry.setId(String.valueOf(i));
            poetry.setTitle(EsUtils.getTitle().get(i));
            poetry.setContent(EsUtils.getContent().get(i));
            poetry.setWeight(i);
            poetry.setUserId(i % 10);
            index = new IndexQueryBuilder().withId(poetry.getId()).withObject(poetry).build();
            index.setId(poetry.getId());
            list.add(index);
		}
		elasticsearchTemplate.bulkIndex(list);
		Map<String,Object> m=new HashMap<String,Object>(){{
			put("msg","添加诗歌"+EsUtils.getTitle().size()+"首");
		}};
		return m;
	}

	@Override
	public Map<String, Object> singleQuery(String word, Pageable pageble) {
//		word="";
		SearchQuery searcQuery = new NativeSearchQueryBuilder()
				//匹配多字段查询
				.withQuery(QueryBuilders.matchQuery("title",word))
				.withQuery(QueryBuilders.matchQuery("content","闺怨诗 宋·李清照 红藕香残玉簟秋。轻解罗裳，独上兰舟。云中谁寄锦书来？雁字回时，月"))
				//全文字段查询
				//.withQuery(QueryBuilders.queryStringQuery(word)).withPageable(pageble)
				.build();
		
		List<TestPoetry> list = elasticsearchTemplate.queryForList(searcQuery, TestPoetry.class);
		Map<String,Object> m=new HashMap<String,Object>(){{
			put("msg","字符串模糊查询，默认排序。将从所有字段中查找包含传来的word分词后字符串的数据集");
			put("data",list);
		}};
		return m;
	}

	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Class c = Class.forName("com.iflytek.sc.pl.project.es.model.DocBean");	
		Method[] methods=c.getMethods();
		for(int i =0 ;i<methods.length;i++) {
            Method m1 = c.getMethod("setId",Integer.class);
            Object obj = c.newInstance();
            m1.invoke(obj,1);
            Method m2 = c.getMethod("getId");
            System.out.println(m2.invoke(obj));
            System.out.println();
		}
	}

	 /**
     * 使用QueryBuilder
     * termQuery("key", obj) 完全匹配
     * termsQuery("key", obj1, obj2..)   一次匹配多个值
     * matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
     * multiMatchQuery("text", "field1", "field2"..);  匹配多个字段, field有通配符忒行
     * matchAllQuery();         匹配所有文件
     */
	@Override
	public Map<String, Object> queryHighlight(String word, Pageable pageable,String index,String type,String fileName[]) throws ClassNotFoundException {
		Long startTime=System.currentTimeMillis();
        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(true);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        
        //查询对象 加上 双引号 表示强制要求 拆分一起
        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(word, fileName);
//        QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(word);
//        //多字段
//        for(String file:fileName) {
//            queryBuilder.field(file).defaultOperator(Operator.AND);
//        }
        //近似度 默认0没有词间距
//        queryBuilder.phraseSlop(QueryStringQueryBuilder.DEFAULT_PHRASE_SLOP);
        
        SearchRequestBuilder searchRequestBuilder = elasticsearchTemplate.getClient().prepareSearch(index)
                .setFrom(pageable.getPageNumber()).setSize(pageable.getPageSize())
                .setTypes(new String[] {"doc","poetry"}) //多表查询
                //设置查询类型 1.SearchType.DFS_QUERY_THEN_FETCH = 精确查询 2.SearchType.QUERY_THEN_FETCH = 扫描查询,无序
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(queryBuilder)
                //根据评分倒叙
                .addSort("_score",SortOrder.DESC)
                .highlighter(highlightBuilder)
                //设置是否按查询匹配度排序
                .setExplain(true); 
        SearchResponse searchResponse = searchRequestBuilder.get();

        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] hits = searchHits.getHits();
        List<Object> resultList= new ArrayList<Object>();
        for (int i = 0; i < hits.length; i++) {
            SearchHit hit = hits[i];
            String json = hit.getSourceAsString();
            Map<String,Object> dataMap = GsonUtil.parseObject(json, Map.class);
            dataMap.put("id", hit.getId());
            dataMap.put("index", hit.getIndex());
            dataMap.put("type", hit.getType());
            
            Map<String, HighlightField> result = hit.getHighlightFields();
            for(String file:fileName) {
                HighlightField titleField = result.get(file);
                if (titleField !=null) {
                    Text[] titleTexts = titleField.fragments();
                    String title = "";
                    for (Text text : titleTexts) {
                        title += text;
                    }
                    dataMap.put(file, title);
                }
            }
            resultList.add(dataMap);
        }
        Map<String,Object> map = new HashMap<String,Object>(){
        	{
        		put("msg","分词高亮数据");
        		put("total",searchHits.getTotalHits());
        		put("page",pageable.getPageNumber());
        		put("pageSize",pageable.getPageSize());
        		put("data",resultList);
        		put("time", System.currentTimeMillis()-startTime);
        	}
        };
		return map;
	}

	@Override
	public Map<String, Object> zcfg(DocBean docBean) {
		IndexQuery index =null;
		List<IndexQuery> list =new ArrayList<IndexQuery>();
		for(int i=0;i<1;i++) {
			index = new IndexQuery();
			docBean.setCreateTime(new Date());
            index = new IndexQueryBuilder().withObject(docBean).build();
            list.add(index);
		}
		elasticsearchTemplate.bulkIndex(list);
		Map<String,Object> m=new HashMap<String,Object>(){{
			put("msg","导入政策法规"+EsUtils.getTitle().size());
		}};
		
		return m;
	}

	@Override
	public <T> Map<String, Object> del(String id,Class<T> clazz) {
		String str=elasticsearchTemplate.delete(clazz, id);
		Map<String,Object> map = new HashMap<String,Object>(){{
			put("id",str);
		}};
		return map;
	}

}
